package org.easy.tool.common;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.*;
import org.apache.http.impl.cookie.BasicClientCookie;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Valley
 * Created by Valley on 2023/7/14 16:21
 */
public class HttpUtil {

    /**
     * 功能：POST请求
     * 请求参数为url地址，json字符串，建议使用ObjectMapper处理
     */
    public static String post(String url, String json){
        return cn.hutool.http.HttpUtil.post(url, json);
    }

    /**
     * 功能：POST请求
     * 请求参数为url地址，json参数体
     */
    public static String post(String url, Object jsonBody){
        String json = JSONUtil.toJsonStr(jsonBody);
        return cn.hutool.http.HttpUtil.post(url, json);
    }


    /**
     * 功能：POST请求
     * 请求参数为url地址，body表单参数
     */
    public static String post(String url, Map<String, Object> body){
        return cn.hutool.http.HttpUtil.post(url, body);
    }

    /**
     * 功能：GET请求
     * 请求参数为url地址
     */
    public static String get(String url){
        return cn.hutool.http.HttpUtil.get(url, CharsetUtil.CHARSET_UTF_8);
    }

    /**
     * 功能：POST请求上传文件
     * 请求参数为url地址，文件路径
     */
    public static String upload(String url, String file) throws Exception{
        HashMap<String, Object> paramMap = new HashMap<>();
        //文件上传只需将参数中的键指定（默认file），值设为文件对象即可
        // 对于使用者来说，文件上传与普通表单提交并无区别
        paramMap.put("file", FileUtil.file(file));
        return post(url, paramMap);
    }

    /**
     * 功能：HttpClient添加cookie
     */
    public static void addClientCookie(BasicCookieStore store, String key, String value) {
        BasicClientCookie cookie = new BasicClientCookie(key, value);
        cookie.setPath("/");
        store.addCookie(cookie);
    }

    /**
     * 功能：通过构造Post请求下载文件到指定位置
     */
    public static void postExport(String url, String json, String path, Map<String,String> header, Map<String, String> cookie) throws Exception{

        //组装HttpPost
        HttpPost post = new HttpPost(url);
        //设置Content-Type
        post.setHeader("Content-Type","application/json; charset=UTF-8");
        //设置JSON参数
        StringEntity stringEntity = new StringEntity(json, StandardCharsets.UTF_8);
        post.setEntity(stringEntity);
        //设置cookie
        CookieStore cookieStore = new BasicCookieStore();
        if(cookie != null && cookie.keySet().size() > 0){
            for (Map.Entry<String, String> e : cookie.entrySet()) {
                BasicClientCookie clientCookie = new BasicClientCookie(e.getKey(), e.getValue());
                clientCookie.setPath("/");
                clientCookie.setDomain("localhost");
                cookieStore.addCookie(clientCookie);
            }
        }

        //设置header
        if(header != null && header.keySet().size() > 0){
            for (Map.Entry<String, String> e : header.entrySet()) {
                post.addHeader(e.getKey(), e.getValue());
            }
        }

        //组装Http客户端
        DefaultHttpClient httpclient = new DefaultHttpClient();
        httpclient.setCookieStore(cookieStore);
//        CloseableHttpClient httpclient = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();

        //发送请求
        CloseableHttpResponse httpResponse = httpclient.execute(post);
        InputStream content = httpResponse.getEntity().getContent();
        FileIOUtil.inputToFile(content, path);
        content.close();
        httpResponse.close();
        httpclient.close();
    }

    /**
     * 功能：下载网络链接文件到文件输出流
     *
     */
    public static long download(String url, OutputStream out) {
        return cn.hutool.http.HttpUtil.download(url, out, true);
    }

    /**
     * 功能：下载网络链接文件到指定文件夹
     */
    public static long download(String url, String dest) {
        return cn.hutool.http.HttpUtil.downloadFile(url, dest);
    }

    /**
     * 功能：下载网络链接文件到指定文件夹，允许设置超时时间
     */
    public static long download(String url, String dest, int timeout) {
        return cn.hutool.http.HttpUtil.downloadFile(url, new File(dest), timeout);
    }

    /**
     * 功能：url编码
     */
    public static String urlEncode(String origin) {
        String[] split = origin.split("\\?");
        String url = URLUtil.encode(split[0]);
        if (split.length >= 2){
            String encode = URLUtil.encode(split[1]);
            url = url + "?" + encode;
        }
        return url;
    }

    /**
     * 功能：从响应流中获取文件并下载到本地
     */
    public static void demo() {

    }

    /**
     * 功能：实现下载文件到浏览器, 这个不好用，推荐使用IOUtil.download(req, res, docPath);
     */
    @Deprecated
    public static void downloadFile(HttpServletRequest req, HttpServletResponse res, File file) throws Exception{
        // 1.读取要下载的内容
        InputStream in = Files.newInputStream(file.toPath());
        // 2. 告诉浏览器下载的方式以及一些设置
        // 解决文件名乱码问题，获取浏览器类型，转换对应文件名编码格式，IE要求文件名必须是utf-8, firefo要求是iso-8859-1编码
        String agent = req.getHeader("user-agent");
        String filename = file.getName();
        if (agent.contains("FireFox")) {
            filename = new String(filename.getBytes("UTF-8"), "iso-8859-1");
        } else {
            filename = urlEncode(filename);
        }
        // 设置下载文件的mineType，告诉浏览器下载文件类型
        String mineType = req.getServletContext().getMimeType(filename);
        res.setContentType(mineType);
        // 设置一个响应头，无论是否被浏览器解析，都下载
        res.setHeader("Content-disposition", "attachment; filename=" + filename);
        // 将要下载的文件内容通过输出流写到浏览器
        OutputStream out = res.getOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }
        out.flush();
        in.close();
    }

    /**
     * 功能：实现渲染文件到请求返回值，type=download为下载，否则为预览
     */
    public static void preview(HttpServletRequest request, HttpServletResponse response, String filePath) throws Exception{
        String type = request.getParameter("type");
        response.reset();
        response.setCharacterEncoding("UTF-8");
        File file = new File(filePath);
        FileInputStream fis = new FileInputStream(file);
        if ("download".equalsIgnoreCase(type)) {
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + System.currentTimeMillis() + filePath.substring(filePath.lastIndexOf(".")));
        }
        OutputStream os = response.getOutputStream();
        byte[] bytes = new byte[1024];
        int length = 0;
        while ((length = fis.read(bytes)) != -1) {
            os.write(bytes, 0, length);
        }
        os.close();
        fis.close();
    }


}
